Event Handling in SproutCore 1.0 - Part 1

written by admin

SproutCore is one of the first JavaScript frameworks to implement event delegation throughout the entire framework.  In this series of blog posts I’m going to explain a bit about how event delegation works and how you use it to handle events in SproutCore Views.

For starters, let’s talk about what event delegation is and how its handled in SproutCore.

What is Event Delegation?

Event delegation is a much faster and simpler way of handling events.  Rather than register listeners for every DOM event you might be interested in on a page, SproutCore delegates responsibility for handling events to just six listeners added to the window and document objects.  These listeners take responsibility for calling any Views that are interested in any event that comes in.

Take the simple example shown below.  This diagram shows a simple document with a button.  When you press the mousedown on the button, it calls a method on a corresponding “View” object in JavaScript:

Regular Delegation

So how does this look with event delegation?

In SproutCore, the object that receives delegated events is called the RootResponder.  (You can find it in your running app at SC.RootResponder.responder).  The RootResponder listens for a mousedown event on the document object.  When this event occurs, the browser will fill in a target property on the event to tell you which DOM element received the event.  The RootResponder uses this property to determine which view should actually be notified of the event, in this case the button view.

The diagram below shows how this works.

Event Delegation

For a web application, which may be interested in hundreds of events on many different DOM elements all over the page, it’s easy to see how event delegation can really improve performance.  Rather than registering event handlers for each of these DOM elements/events, SproutCore only registers six.  It waits until an event actually occurs on your page before taking the time to figure out which part of your application actually needs to handle the event.

(By the way, some other libraries are starting to implement event delegation as well.  jQuery and Prototype both are getting this feature to varying degrees.  SproutCore takes this feature a lot further than most, but as apps grow in complexity I expect this to appear in lots of other places as well so its useful to know how this technique works.)

Listening for Events

If you don’t register listeners, how do you indicate you are interested in an event?

In SproutCore this is very simple.  When you define your view subclass, just add methods to handle the events you are interested in.  (For more on creating Views in SproutCore see frozencanuck’s tutorials part 1 and part 2.)

For example, mouseDown() is called whenever a user presses the mouse button over the top of your view’s HTML.  To respond to this event, just add the method:

> > MyApp.MyView = SC.View.extend({ > // called whenever a mouse down event occurs > mouseDown: function(evt) { > // do something interesting here > } > }); > > >

That’s all you need to do.  Now your view can respond to mouseDown events.

Usually when writing SproutCore applications, it best to try to ignore the underlying HTML in your document altogether and just let SproutCore handle it.  However if you ever really need to know which HTML element the user needs to click on to get mouseDown(), it is stored in the “layer” property.  Just call:

this.get('layer')

on your view once it is onscreen.

Note that SproutCore defines events slightly differently than the built-in browser events.  In particular “click” and “dblclick” are ignored.  ”mouseover” and “mouseout” are also implemented more sanely.   Keyboard event handling also requires a better understanding of the Responder chain - SproutCore’s focus management system.

I’ll cover these more in the next blog post.

Any other topics you want covered?  Let me know in the comments!

Blog Roundup 8-19

written by admin

The blog posts are coming fast and furious these days with tons of really useful information on using the SproutCore API.  Here’s a couple that I know about:

It’s Got What Plants Crave » Basic View API (part 1) - great introduction to the View API.  This is a good followup to earlier posts by frozencanuck that take you on a tutorial through the view API.

Frozencanuck » Formatting a String in SproutCore with fmt - The String.fmt() method is a great way to generate combined strings.  This post shows you how.  Note also the String.loc() method, which does the same thing as fmt() but will attempt to localize  your string for you also.

Aspect-Oriented Programming and You

written by admin

One of the coolest parts of the new SproutCore View layer is its ability to use aspect-based programming to add behaviors to views.

Aspect-based programming is built on the premise that often objects that don’t follow from the same class hierarchy may in fact need similar behaviors.

This is especially true in GUI programming when designers come to you and say something like “I came up with this new widget - it looks kind of like a progress bar but it acts like a button when you click on it”.

In SproutCore, you capture these common behaviors in a “mixin”.  A mixin is just a collection or properties and methods that are added to your class when you define it.  The view layer will actually look for specific hooks on your mixin so that you can automatically hook into the drawing engine, listen for events, etc.  It’s very powerful.

Take the example above: with the button-y progress bar.    SproutCore has an SC.Button mixin that implements button-like behavior.  Just apply it to an SC.ProgressView and update a few hooks to get the API you want.

`MyApp.ProgressButton = SC.ProgressView.extend(SC.Button, { > > // ... extra properties here > > > > }); > > `

SproutCore comes with built in aspects that implement most of its common APIs including managing content properties (SC.Control, SC.ContentDisplay), rendering (SC.Border, SC.Shadow), and some behaviors (SC.Button).

Over time I expect we’ll add more.  In the mean time, this is a great technique to learn to rapidly build high-quality views with composite behaviors without having to rewrite code.

If you want a further example of how mixins can be used, take a look at this tutorial by FrozenCanuck on using the SC.ContentDisplay mixin to easily auto-render a bunch of properties on a content object.